import java.io.*;
import java.net.*;
import java.util.*;
import java.sql.*;


public class ServerThread extends Thread{

    private String[][] matriz;
    private Socket socket;
    private String user, password, op;
    private BufferedReader input;
    private BufferedWriter writer;
    private Encryption enc;
    private int num_lines, many_users, user_port;
    private String username, userIP;


    public ServerThread(Socket socket){
        this.socket = socket;
        enc = new Encryption();
        try{
            writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            input = new BufferedReader(new InputStreamReader(socket.getInputStream()));

            /* Get Adress */
            userIP = socket.getRemoteSocketAddress().toString();
        }catch(Exception e){e.printStackTrace();}
    }

    public void run(){
        try{

            getUserName();
            getUserPort();
            setUserAddress();
            MontarMatriz();
            TratarEntrada();

        }catch(Exception e){e.printStackTrace();}
        return;
    }

    /* Coloca no arquivo de usuarios o endereco deste usuario */
    public void setUserAddress(){

        try{ 
            /* Criar um arquivo temporario para modificacao */
            File temp_file = new File("./files/TempAddressBook");
            File original = new File("./files/AddressBook");
            BufferedWriter out_temp = new BufferedWriter(new FileWriter(temp_file));


            /* Ver se ja existe seu endereco no arquivo */
            BufferedReader input_file = new BufferedReader(new FileReader(original));
            String line = "";
            line = input_file.readLine();
            many_users = Integer.parseInt(line);
            int already=0;
            System.out.println("AddressBook contem o endereco de "+many_users+" usuarios");
            int aux=many_users;

            for(int i=0;i<many_users;i++){
                line = input_file.readLine();
                String[] parts = line.split("_");
                if((parts[0].compareTo(username))==0){
                    already=1; 
                    aux--;
                }
            }
            many_users = aux;
            input_file.close();

            /* Recriar o arquivo em TempAddressBook */
            input_file = new BufferedReader(new FileReader(original));
            input_file.readLine();
            many_users++;
            System.out.println("Gerando arquivo temporario");
            System.out.println("Ira conter "+many_users+" usuarios");
            out_temp.write(many_users+"\n");
            out_temp.flush();
            
            if(already==1){
                for(int i=0;i<(many_users);i++){
                    line = input_file.readLine();
                    System.out.println("Line "+i+" "+line);
                    String[] parts = line.split("_");
                    if((parts[0].compareTo(username))!=0){
                        out_temp.write(line+"\n");
                    }
                }
            }
            
            else{
                for(int i=0;i<(many_users-1);i++){
                    line = input_file.readLine();
                    System.out.println("Line "+i+" "+line);
                    out_temp.write(line+"\n");
                }
            }

            out_temp.write(username+"_"+userIP+"_"+user_port+"\n");
            out_temp.flush();
            out_temp.close();
            original.delete();
            temp_file.renameTo(original);


        }catch(Exception e){ System.out.println(e.getMessage());}

    }

    public void getUserName(){

        try{
            username = input.readLine();
            username = enc.decrypt(username);
            System.out.println("User name: "+username);
        }catch(Exception e){e.printStackTrace();}

    }

    public void getUserPort(){

        String aux = "";

        try{

            aux = input.readLine();
            aux = enc.decrypt(aux);
            String[] parts = aux.split("_");

            user_port = Integer.parseInt(parts[1]);


        }catch(Exception e){e.printStackTrace();}

    }


    public void Escrever(String msgm){

        try{
            msgm = enc.encrypt(msgm);
            writer.write(msgm);
            writer.newLine();
            writer.flush();
        }catch(Exception e){e.printStackTrace();}

    }

    public void TratarEntrada(){

        String msgm = "";

        while((msgm.compareTo("exit"))!=0){

            try{ 
                msgm = input.readLine();
                msgm = enc.decrypt(msgm);
                System.out.println("Comando: "+msgm);

                if((msgm.compareTo("AllFiles"))==0){

                    String all_files = "";
                    for(int i=0;i<num_lines;i++){
                        all_files = all_files.concat(matriz[i][0]); 
                        if(i<(num_lines-1))
                            all_files = all_files.concat("_");
                    }

                    System.out.println("All Files: "+all_files);
                    Escrever(all_files);
                }
                if((msgm.compareTo("MyFiles"))==0){

                    String all_files = "";
                    for(int i=0;i<num_lines;i++){
                        if((matriz[i][1].compareTo(username))==0){
                            all_files = all_files.concat(matriz[i][0]); 
                            if(i<(num_lines-1))
                                all_files = all_files.concat("_");
                        }
                    }
                    System.out.println("My Files: "+all_files);
                    Escrever(all_files);
                }
                if((msgm.compareTo("GetFile"))==0){

                    String fileName = input.readLine();
                    System.out.println(fileName);
                    fileName = enc.decrypt(fileName);
                    System.out.println(fileName);

                    /* Check se o arquivo existe */
                    if(checkFile(fileName)){
                        Escrever("FileFound");
                        /* Se o arquivo existir, pegar o endereco de quem tem */
                        String owners = whoHas(fileName);
                        Escrever(owners);

                        /* O usuario irá pedir o endereco de algum outro usuario */
                        msgm = input.readLine();
                        msgm = enc.decrypt(msgm);

                        System.out.println("Usuario quer o endereco de : "+msgm);

                        Escrever(getAddress(msgm));

                    }
                    else
                        Escrever("FileNotFound");
                }
                if((msgm.compareTo("AddFile"))==0){

                    /* Recebe o nome do arquivo */
                    String fileName = input.readLine();
                    fileName = enc.decrypt(fileName);

                    /* Adiciona ao arquivo de controle */

                    AddFile(fileName);
                    System.out.println("Arquivo "+fileName+" foi adicionado pelo usuario "+username);

                }
                if((msgm.compareTo("UpdateFiles"))==0){

                    MontarMatriz();

                }
                if((msgm.compareTo("RemoveFile"))==0){

                    
                    String fileName = input.readLine();
                    fileName = enc.decrypt(fileName);

                    /* Adiciona ao arquivo de controle */

                    RmFile(fileName);
                    System.out.println("Arquivo "+fileName+" foi removido pelo usuario "+username);

                }

            }catch(Exception e){e.printStackTrace();}
        }

    }

    public void RmFile(String fileName){
    
        try{ 

            /* Criar um arquivo temporario para modificacao */
            File temp_file = new File("./files/TempFileManager");
            File original = new File("./files/FileManager.txt");
            BufferedWriter out_temp = new BufferedWriter(new FileWriter(temp_file));
            BufferedReader input_file = new BufferedReader(new FileReader(original));
            String line = "";
            String[] parts;
            int many_lines = Integer.parseInt(input_file.readLine());
            int count=0;

            /* For que conta quantas linhas serao retiradas */
            for(int i=0;i<(many_lines);i++){
                line = input_file.readLine();
                parts = line.split("_");
                if((parts[0].compareTo(fileName))==0 && (parts[1].compareTo(username))==0){
                    System.out.println("Arquivo para remocao");
                    count++;
                }
            }


            /* Reescreve o original no temporario, mudando a primeira linha para many_lines++ */

            out_temp.write((many_lines-count)+"\n");
            out_temp.flush();
            input_file.close();
            
            input_file = new BufferedReader(new FileReader(original));
            line = input_file.readLine();

            for(int i=0;i<(many_lines);i++){
                line = input_file.readLine();
                parts = line.split("_");
                if((parts[0].compareTo(fileName))!=0 && (parts[1].compareTo(username))!=0)
                    out_temp.write(line+"\n");
            }


            out_temp.close();
            original.delete();
            temp_file.renameTo(original);


        }catch(Exception e){ System.out.println(e.getMessage());}
    
    }


    public void AddFile(String fileName){

        try{ 

            /* Criar um arquivo temporario para modificacao */
            File temp_file = new File("./files/TempFileManager");
            File original = new File("./files/FileManager.txt");
            BufferedWriter out_temp = new BufferedWriter(new FileWriter(temp_file));
            BufferedReader input_file = new BufferedReader(new FileReader(original));

            int many_lines = Integer.parseInt(input_file.readLine());

            /* Reescreve o original no temporario, mudando a primeira linha para many_lines++ */
            many_lines++;
            out_temp.write(many_lines+"\n");

            String line = "";

            for(int i=0;i<(many_lines-1);i++){
                line = input_file.readLine();
                out_temp.write(line+"\n");
            }


            out_temp.write(fileName+"_"+username+"_0\n");
            out_temp.close();
            original.delete();
            temp_file.renameTo(original);


        }catch(Exception e){ System.out.println(e.getMessage());}

    }


    /* Funcao que retorna o endereco do usuario */
    public String getAddress(String username){

        try{
            File original = new File("./files/AddressBook");
            BufferedReader input_file = new BufferedReader(new FileReader(original));
            String msgm="";
            int many_users = Integer.parseInt(input_file.readLine());
            System.out.println("O arquivo contem "+many_users+" linhas");
            for(int i=0;i<many_users;i++){
                msgm = input_file.readLine();
                String[] parts = msgm.split("_");
                if((parts[0].compareTo(username))==0){
                    return (parts[1]+"_"+parts[2]);
                }
            }
        }catch(Exception e){e.printStackTrace();}
        return "AddressNotFound";
    }

    /* funcao que retorna um String com os nomes dos ususarios que tem o arquivo */
    public String whoHas(String fileName){

        String owners = "";
        for(int i=0;i<num_lines;i++){
            if((matriz[i][0].compareTo(fileName))==0){
                owners = owners.concat(matriz[i][1]);
                if(i<(num_lines-1))
                    owners = owners.concat("_");
            }
        }
        return owners;
    }

    public boolean checkFile(String name){

        for(int i=0;i<num_lines;i++){
            if((matriz[i][0].compareTo(name))==0){
                return true;
            }
        }
        return false;
    }

    public void MontarMatriz(){

        try{

            BufferedReader input_file = new BufferedReader(new FileReader("./files/FileManager.txt"));
            String line = "";
            String fileName, userName, changed;
            String[] parts;
            int i=0;

            while((line=input_file.readLine())!=null){
                if(i==0){
                    num_lines = Integer.parseInt(line);
                    matriz = new String[num_lines][3];
                }
                else{

                    // System.out.println(line);

                    parts = line.split("_");

                    fileName = parts[0];
                    userName = parts[1];
                    changed = parts[2];

                    matriz[i-1][0] = fileName;
                    matriz[i-1][1] = userName;
                    matriz[i-1][2] = changed;

                }
                i++;


            }
        }catch(Exception e){ e.printStackTrace();}
    }

}


